package utils

import (
	"crypto/rand"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"strings"
	"time"
)

// UUID 表示一个 UUID
type UUID [16]byte

var (
	ErrInvalidUUID = errors.New("invalid UUID")
	Nil            = UUID{}
)

// UUIDNewV1 生成一个版本 1（基于时间）的 UUID
func UUIDNewV1() (UUID, error) {
	var uuid UUID
	now := time.Now().UnixNano()/100 + 0x01b21dd213814000
	binary.BigEndian.PutUint32(uuid[0:], uint32(now&0xffffffff))
	binary.BigEndian.PutUint16(uuid[4:], uint16((now>>32)&0xffff))
	binary.BigEndian.PutUint16(uuid[6:], uint16((now>>48)&0x0fff))
	uuid[6] = (uuid[6] & 0x0f) | 0x10 // 版本 1

	_, err := io.ReadFull(rand.Reader, uuid[8:])
	if err != nil {
		return Nil, err
	}
	uuid[8] = (uuid[8] & 0x3f) | 0x80 // 变体

	return uuid, nil
}

// UUIDNewV4 生成一个版本 4（随机）的 UUID
func UUIDNewV4() (UUID, error) {
	var uuid UUID
	_, err := io.ReadFull(rand.Reader, uuid[:])
	if err != nil {
		return Nil, err
	}
	uuid[6] = (uuid[6] & 0x0f) | 0x40 // 版本 4
	uuid[8] = (uuid[8] & 0x3f) | 0x80 // 变体
	return uuid, nil
}

// UUIDParse 从字符串解析 UUID
func UUIDParse(s string) (UUID, error) {
	var uuid UUID
	s = strings.Replace(s, "-", "", -1)
	if len(s) != 32 {
		return Nil, ErrInvalidUUID
	}
	_, err := hex.Decode(uuid[:], []byte(s))
	return uuid, err
}

// UUIDString 将 UUID 转换为字符串
func (uuid UUID) UUIDString() string {
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
}

// UUIDEqual 比较两个 UUID 是否相等
func (uuid UUID) UUIDEqual(other UUID) bool {
	return uuid == other
}

// UUIDIsNil 检查 UUID 是否为空（全零）
func (uuid UUID) UUIDIsNil() bool {
	return uuid == Nil
}

// UUIDVersion 返回 UUID 的版本
func (uuid UUID) UUIDVersion() int {
	return int(uuid[6] >> 4)
}

// UUIDVariant 返回 UUID 的变体
func (uuid UUID) UUIDVariant() int {
	switch {
	case (uuid[8] & 0x80) == 0x00:
		return 0
	case (uuid[8] & 0xc0) == 0x80:
		return 1
	case (uuid[8] & 0xe0) == 0xc0:
		return 2
	}
	return 3
}
